#ifndef INFINITY_PLANET_H
#	define INFINITY_PLANET_H

#include "planetshape.h"
#include "materiallibrary.h"
#include "itemmateriallibrary.h"



namespace infinity {

class TerrainGenerator;

class Planet
{
public : //! @name Types definitions
	//! @{
	class Area;
	class Sector;
	class Cell;
	class Item;
	class Cache;

	class EventListener;

	class EventArg;
	class CellEventArg;
	//! @}

public : //! @name Construction & Destruction
	//! @{
	Planet(TerrainGenerator* generator, dw::int32 radius);
	~Planet();
	//! @}

public : //! @name Commands
	//! @{
	void install();
	void term();

	void registerListener(EventListener* listener);
	void unregisterListener(EventListener* listener);

	void save(const char* filePath);
	static Planet* load(const char* filePath);
	//! @}

public : //! @name State
	//! @{
	dw::int32 getRadius() const ;
	const MaterialLibrary& getMaterialLibrary() const { return m_materialLibrary; }
	const ItemMaterialLibrary& getItemMaterialLibrary() const { return m_itemMaterialLibrary; }

	void getCell(const Vector3i& coords, Cell& cell) const ;
	bool getItem(const Vector3i& coords, Item& item) const ;
	//! @}

public : //! @name State
	//! @{
	//! @todo setCell -> Area + sector
	void setCell(const Vector3i& coords, const Cell& cell, float power = 1.0f);
	void setCellUser(const dw::int64 key, const Cell& cell);

	void setItem(const Vector3i& coords, const Item& item);
	void setItemUser(const dw::int64 key, const Item& item);

	void removeItem(const Vector3i& coords);

	void boom(const Vector3i& coords, float radius, float power);
	//! @}

private : //! @name Events
	//! @{
	void onCellChanged(CellEventArg& arg);
	float SphereEval(int x,int y,int z, float power);
	//! @}

private : //! @name Helpers
	//! @{
	void generateCell(const Vector3i& coords, Cell& cell) const ;
	bool getInCellUser(const Vector3i& coords, Cell& cell) const ;
	bool getInItemUser(const Vector3i& coords, Item& item) const ;
	//! @}

private : //! @name Types definitions
	//! @{
	typedef std::vector< EventListener* > ListenersCollection;

	typedef std::map< dw::uint64, Cell > CellUserDeltaMap;
	typedef CellUserDeltaMap::const_iterator CellUserDeltaIterator;

	typedef std::map< dw::uint64, Item > ItemUserMap;
	typedef ItemUserMap::const_iterator ItemUserIterator;


private : //! @name Data
	//! @{
	dw::int32 m_radius;
	MaterialLibrary m_materialLibrary;
	ItemMaterialLibrary m_itemMaterialLibrary;

	// user Delta
	CellUserDeltaMap m_cellUserDelta;
	ItemUserMap m_itemUser;

	ListenersCollection m_listeners;

	TerrainGenerator* m_generator;

	Cell* m_cells;
	//! @}
};

} // namespace infinity

#endif // !INFINITY_PLANET_H
